#include "GY_ADI.h"
#include <QDebug>
#include "Graphics/GY_GraphicsReflection.h"

GY_ADI::GY_ADI(const QString &guid, QGraphicsItem *parent) : GY_ContainerTransform(guid,this,parent)
{
    initializationPropertyInfo();
    this->setCenterPointF(m_PropertyInfoMap["Position"].propertyValue.toPointF());
    m_pTransFormGroupRotate = new GY_TransformGroup(QString("%1_GroupRotate").arg(guid),this);
    m_pTransFormGroupSlide = new GY_TransformGroup(QString("%1_GroupSlide").arg(guid),this);
    m_pClippingToolContainer = new GY_ClippingToolContainer(QString("%1_ClippingTool").arg(guid),this);
    m_pClippingToolContainer->setPos(QPointF(0,0));
    m_pRect = new QGraphicsRectItem(this);
    this->addToGroup(m_pClippingToolContainer);
    m_ChildrensMap.insert(m_pClippingToolContainer->getGuid(),m_pClippingToolContainer);
    //旋转层控制旋转点位不变
    m_pClippingToolContainer->addItem((GY_Object*)m_pTransFormGroupRotate);
    //俯视仰视，控制图元位置
    m_pTransFormGroupRotate->addItem((GY_Object*)m_pTransFormGroupSlide);
    setContainerEditPointF();
}

GY_ADI::~GY_ADI()
{

}

void GY_ADI::setContainerEditPointF()
{
    QMap<QVariant,QPointF> editPoints = {
        {"Point",m_PropertyInfoMap["Point"].propertyValue.toPointF()}
    };
    this->setEditPointF(editPoints);
}

GY_Object *GY_ADI::copyItem(const QString &guid)
{
    if(getUserData(GY_ENUM::IsCopy) == 1) {
        GY_Object *tmp;
        this->copyItemSig(&tmp);
        //更新copyItem属性列表
        QMap<QString,GY_PropertyInfo>::Iterator iterProperty = m_PropertyInfoMap.begin();
        while (iterProperty != m_PropertyInfoMap.end()) {
            if(((iterProperty.value().updateType)&PointOfRelative) == PointOfRelative) {
                tmp->updateProperty(iterProperty.key(), submittingPropertyValues(iterProperty.value().updateType,iterProperty.value().propertyValue,this));
            }else if(((iterProperty.value().updateType)&NotUpdate) == NotUpdate){
                ++iterProperty;
                continue;
            }else {
                tmp->updateProperty(iterProperty.key(), iterProperty.value().propertyValue);
            }
            ++iterProperty;
        }
        return tmp;
    }
    GY_Object* pObj;
    if(guid.isEmpty()) {
        pObj = (GY_Object*)GY_GraphicsReflection::getInstance()->newInstanceObjectClass(this->metaObject()->className(),this->getGuid()+"-"+QString::number(m_MyGuid));
        m_MyGuid++;
    }else {
        pObj = (GY_Object*)GY_GraphicsReflection::getInstance()->newInstanceObjectClass(this->metaObject()->className(),guid);
    }
    if(pObj == nullptr) {
        qDebug()<<this->getGuid()<<"isEmpty";
        return nullptr;
    }
    QVector<GY_Object *> childrens = m_pTransFormGroupSlide->getOrderChildrens();
    int childrensSize = childrens.size();
    for(int i=0;i<childrensSize;i++) {
//        if(childrens[i]->copyItem() == nullptr) {
//            qDebug()<<childrens[i]->getGuid()<<"isEmpty";
//            continue;
//        }
        ((GY_ContainerTransform*)pObj)->addItem(childrens[i]->copyItem());
    }

    QMap<QString,GY_PropertyInfo>::Iterator iterProperty = m_PropertyInfoMap.begin();
    while (iterProperty != m_PropertyInfoMap.end()) {
        if(((iterProperty.value().updateType)&PointOfRelative) == PointOfRelative) {
            pObj->updateProperty(iterProperty.key(), submittingPropertyValues(iterProperty.value().updateType,iterProperty.value().propertyValue,this));
        }else if(((iterProperty.value().updateType)&NotUpdate) == NotUpdate){
            ++iterProperty;
            continue;
        }else {
            pObj->updateProperty(iterProperty.key(), iterProperty.value().propertyValue);
        }
        ++iterProperty;
    }
    connect(pObj,&GY_Object::copyItemSig,this,&GY_Object::originalVersion);
    pObj->setUserData(GY_ENUM::IsCopy, QVariant::fromValue(1));
    return pObj;
}

bool GY_ADI::addItem(GY_Object *pItem)
{
    m_pTransFormGroupSlide->addItem((GY_Object*)pItem);
    //添加item之后重新添加组，捕获编辑点更精确
    this->addToGroup(m_pClippingToolContainer);
    updateDraw();
    return true;
}

bool GY_ADI::removItem(const QString &guid)
{
    return m_pTransFormGroupSlide->removItem(guid);
}

bool GY_ADI::removItem(const GY_Object *pItem)
{
    bool remove = m_pTransFormGroupSlide->removItem((GY_Object*)pItem);
    m_pTransFormGroupRotate->removItem((GY_Object*)pItem);
    m_pClippingToolContainer->removItem((GY_Object*)pItem);
    this->GY_ContainerTransform::removItem((GY_Object*)pItem);
    updateDraw();
    return remove;
}

void GY_ADI::initializationPropertyInfo()
{
    GY_PropertyInfo ObjectName(this);
    ObjectName.propertyName = "ObjectName";
    ObjectName.propertyValue = QString();
    ObjectName.updateType = Update|OrdinaryAttributes;
    ObjectName.propertyType = QStringPropertyType;
    ObjectName.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_ADI::updateObjectName;
    m_PropertyInfoMap.insert("ObjectName",ObjectName);
    m_PropertyInfoMap[ObjectName.propertyName].setConnect();

    //位置
    GY_PropertyInfo positonPropertyInfo(this);
    positonPropertyInfo.propertyName="Position";
    positonPropertyInfo.propertyValue=QPointF(0,0);
    positonPropertyInfo.updateType = Update|MoveUpdate|PointOfRelative;
    positonPropertyInfo.propertyType = PointPropertyType;
    positonPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ADI::updatePosition;
    m_PropertyInfoMap.insert(positonPropertyInfo.propertyName,positonPropertyInfo);
    m_PropertyInfoMap[positonPropertyInfo.propertyName].setConnect();

    //编辑点
    GY_PropertyInfo pointPropertyInfo(this);
    pointPropertyInfo.propertyName="Point";
    pointPropertyInfo.propertyValue=QPointF(100,100);
    pointPropertyInfo.updateType = NotUpdate;
    pointPropertyInfo.propertyType = PointPropertyType;
    pointPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ADI::updatePoint;
    m_PropertyInfoMap.insert(pointPropertyInfo.propertyName,pointPropertyInfo);
    m_PropertyInfoMap[pointPropertyInfo.propertyName].setConnect();

    GY_PropertyInfo sizePropertyInfo(this);
    sizePropertyInfo.propertyName="Size";
    sizePropertyInfo.propertyValue=QPointF(100,100);
    sizePropertyInfo.updateType = Update|OrdinaryAttributes;
    sizePropertyInfo.propertyType = PointPropertyType;
    sizePropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ADI::updateSize;
    m_PropertyInfoMap.insert(sizePropertyInfo.propertyName,sizePropertyInfo);
    m_PropertyInfoMap[sizePropertyInfo.propertyName].setConnect();

    GY_PropertyInfo rotationCenterPropertyInfo(this);
    rotationCenterPropertyInfo.propertyName="RotationCenter";
    rotationCenterPropertyInfo.propertyValue=QPointF(0,0);
    rotationCenterPropertyInfo.updateType = Update|OrdinaryAttributes;
    rotationCenterPropertyInfo.propertyType = PointPropertyType;
    rotationCenterPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ADI::updateRotationCenter;
    m_PropertyInfoMap.insert(rotationCenterPropertyInfo.propertyName,rotationCenterPropertyInfo);
    m_PropertyInfoMap[rotationCenterPropertyInfo.propertyName].setConnect();

    GY_PropertyInfo maximumPitchPropertyInfo(this);
    maximumPitchPropertyInfo.propertyName="MaximumPitch";
    maximumPitchPropertyInfo.propertyValue=90;
    maximumPitchPropertyInfo.updateType = Update|OrdinaryAttributes;
    maximumPitchPropertyInfo.propertyType = QrealPropertyType;
    maximumPitchPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ADI::updateMaximumPitch;
    m_PropertyInfoMap.insert(maximumPitchPropertyInfo.propertyName,maximumPitchPropertyInfo);
    m_PropertyInfoMap[maximumPitchPropertyInfo.propertyName].setConnect();

    GY_PropertyInfo rollPropertyInfo(this);
    rollPropertyInfo.propertyName="Roll";
    rollPropertyInfo.propertyValue=0;
    rollPropertyInfo.updateType = Update|OrdinaryAttributes;
    rollPropertyInfo.propertyType = QrealPropertyType;
    rollPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ADI::updateRoll;
    m_PropertyInfoMap.insert(rollPropertyInfo.propertyName,rollPropertyInfo);
    m_PropertyInfoMap[rollPropertyInfo.propertyName].setConnect();

    GY_PropertyInfo pitchPropertyInfo(this);
    pitchPropertyInfo.propertyName="Pitch";
    pitchPropertyInfo.propertyValue=0;
    pitchPropertyInfo.updateType = Update|OrdinaryAttributes;
    pitchPropertyInfo.propertyType = QrealPropertyType;
    pitchPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ADI::updatePitch;
    m_PropertyInfoMap.insert(pitchPropertyInfo.propertyName,pitchPropertyInfo);
    m_PropertyInfoMap[pitchPropertyInfo.propertyName].setConnect();

}

void GY_ADI::updateDraw()
{
    qreal maxPitch = m_PropertyInfoMap["MaximumPitch"].propertyValue.toReal();
    qreal pitch = m_PropertyInfoMap["Pitch"].propertyValue.toReal();
    qreal proportion = pitch/maxPitch;
    m_pTransFormGroupSlide->setPos(QPointF(0,-(proportion*(m_pTransFormGroupSlide->childrenBoundingRect().height()/2))));

    QPointF rotationCenter = m_PropertyInfoMap["RotationCenter"].propertyValue.toPointF();
    QPointF size = m_PropertyInfoMap["Size"].propertyValue.toPointF();
    QPointF center;
    center.setX(rotationCenter.x()*size.x());
    center.setY(rotationCenter.y()*size.y());
    m_pTransFormGroupRotate->setPos(center);

    qreal roll = m_PropertyInfoMap["Roll"].propertyValue.toReal();
    QTransform form;
    form.rotate(roll);
    m_pTransFormGroupRotate->setTransform(form);

    QPainterPath path;
    QPointF point1 = m_PropertyInfoMap["Position"].propertyValue.toPointF();
    QPointF point2 = m_PropertyInfoMap["Size"].propertyValue.toPointF();
    qreal width = point2.x()-point1.x();
    qreal height = point2.y()-point1.y();
    QRectF rect = QRectF(point1.x(),point1.y(), width, height);
    path.addRect(rect);
    this->removeFromGroup(m_pRect);
    m_pRect->setRect(rect);
    this->addToGroup(m_pRect);
    m_pClippingToolContainer->setIsCut(true);
    m_pClippingToolContainer->setShape(path);
}

bool GY_ADI::updatePosition(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    //setpos设置为父级坐标
    QPointF point = value.toPointF();
    if(this->parentItem()) {
        point = this->mapToParent(this->mapFromScene(value.toPointF()));
    }
    this->setPos(point);
    m_PropertyInfoMap[name].propertyValue=this->mapFromScene(value.toPointF());
    updateDraw();
    return true;
}

bool GY_ADI::updatePoint(const QString &, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    m_PropertyInfoMap["Size"].propertyValue = this->mapFromScene(value.toPointF());
    this->setEditPointF("Point",this->mapFromScene(value.toPointF()));
    updateDraw();
    return true;
}

bool GY_ADI::updateSize(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue = value;
    this->setEditPointF("Point",(value.toPointF()));
    updateDraw();
    return true;
}

bool GY_ADI::updateRotationCenter(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue = value;
    updateDraw();
    return true;
}

bool GY_ADI::updateMaximumPitch(const QString &name, const QVariant &value)
{
    if(!value.canConvert<qreal>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value.toReal();
    updateDraw();
    return true;
}

bool GY_ADI::updateRoll(const QString &name, const QVariant &value)
{
    if(!value.canConvert<qreal>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value.toReal();
    updateDraw();
    return true;
}

bool GY_ADI::updatePitch(const QString &name, const QVariant &value)
{
    if(!value.canConvert<qreal>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value.toReal();
    updateDraw();
    return true;
}
